home *** CD-ROM | disk | FTP | other *** search
/ Creative Computers / Creative Computers CD-ROM, Volume 1 (Legendary Design Technologies, Inc.)(1994).iso / commercial / sunrize / psound_3.1 / public_domain / sound / sound.c < prev    next >
C/C++ Source or Header  |  1994-11-17  |  19KB  |  575 lines

  1. /****************************   Sound.c   *********************************
  2.  
  3.     Sound is copyright (c) 1988 by Richard Lee Stockton, 21305 60th Ave W.,
  4. Mountlake Terrace, Washington 98043, 206/776-1253(voice), but may be freely
  5. distributed as long as no profit is made from its distribution or sale
  6. without my written permission. I call this concept 'FreeWare', you can
  7. call it whatcha want.
  8.  
  9.     I also include the source code, (Manx 3.4/3.6), in the hope that it
  10. will be of benefit to someone in the Amiga programming community. Feel free
  11. to alter it at will, (but at your own risk!). I _would_ appreciate
  12. receiving a copy of whatever it may become and it is always nice to receive
  13. credit, (perhaps just a few lines of glowing tribute.^)
  14.  
  15.                Long Live Leo and All the Little Schwabies!
  16.  
  17.                     To Manufacture with Manx 3.4/3.6:
  18.  
  19.                             cc Sound.c
  20.                             ln +cd Sound.o -lc
  21.  
  22.      You'll get a warning that you've re-defined IconBase. Ignore it.
  23.  
  24. **************************************************************************/
  25.  
  26. #include <exec/memory.h>
  27. #include <workbench/startup.h>
  28. #include <workbench/workbench.h>
  29. #include <workbench/icon.h>
  30. #include <libraries/dosextens.h>
  31. #include <devices/audio.h>
  32. #include <functions.h>
  33.  
  34. /* Less than WorkBench 1.2 need not apply. That's nobody, right? ;-> */
  35.  
  36. #define  REVISION   33L
  37.  
  38. /* We'll need 4 buffers in CHIP memory, all else in FAST, if ya got it */
  39.  
  40. #define  BUFSIZE  1024L
  41.  
  42. /* Some MANX specific, byte saving, (usually), string routines */
  43.  
  44. #define  strcpy     _BUILTIN_strcpy
  45. #define  strcmp     _BUILTIN_strcmp
  46. #define  strlen     _BUILTIN_strlen
  47.  
  48. /* A pretty little HELP message showing valid variable ranges */
  49.  
  50. #define  USAGE      "\
  51. \033[42m\033[31m\
  52.  USAGE: Sound <file> [l/r]  [0-55]   [56-65535]  [on/off]  [QUIET]  \
  53. \033[m\n\033[42m\
  54.  ABORT: <CTRL> 'c'\033[33m\
  55.   CHANNEL CYCLES SAMPLES/SECOND STEREO  NO-WINDOW \
  56. \033[m\n\033[42m\033[31m\
  57.  20-JAN-90 03:08 \xA9 1990 Richard Lee Stockton - freely distributable \
  58. \033[m\n"
  59.  
  60. /* Probably more GLOBALS than are required. 'C' is funny stuff. */
  61.  
  62. extern struct   IconBase      *IconBase=NULL;
  63. extern struct   IntuitionBase *IntuitionBase=NULL;
  64. extern struct   WBStartup     *WBenchMsg=NULL;
  65. extern struct   WBArg         *argp=NULL;
  66.        struct   IntuiMessage  *message=NULL;
  67.        struct   Window        *StatusWindo=NULL;
  68.        struct   DiskObject    *infofile=NULL;
  69.        struct   IOAudio       *sound[4]={NULL,NULL,NULL,NULL};
  70.                 long          sactual=0L, sstart=0L, savelock=0L,
  71.                                atol(), sps=0L, cycles=1L, lock=0L;
  72.                 short         k=0, stereo=0, left=1, right=1,
  73.                                statusline=1;
  74.                 UBYTE         sunit[4]={12,10,5,3},
  75.                                sunitL[2]={1,8}, sunitR[2]={2,4};
  76.                 BOOL          help=FALSE;
  77.                 char          *sbuffer=NULL, *ltoa(), title[50]="Sound: ",
  78.                                *cbuf[4]={NULL,NULL,NULL,NULL},
  79.                                *sname[108]=NULL, *SafeAllocMem();
  80.                 void          loadSound(), setStatusWindo(),
  81.                                soundSound(), cleanup(), quit();
  82.  
  83. /*********** quit, give-up, go home, finish... Neatness counts! ******/
  84.  
  85. void quit(qstring)
  86. char    *qstring;
  87. { cleanup(qstring);  exit(0); }
  88.  
  89. void cleanup(string)
  90. char    *string;
  91. {
  92.    if(sound[0])      /* This cleans up the audio device stuff */
  93.    {
  94.       for(k=3;k>(-1);k--)
  95.       {
  96.          if((sound[k])&&(sound[k]->ioa_Request.io_Device))
  97.             AbortIO(sound[k]);
  98.       }
  99.       if(sound[0]->ioa_Request.io_Device) CloseDevice(sound[0]);
  100.       for(k=3;k>(-1);k--)
  101.       {
  102.          if(sound[k]->ioa_Request.io_Message.mn_ReplyPort)
  103.             DeletePort(sound[k]->ioa_Request.io_Message.mn_ReplyPort);
  104.       }
  105.       for(k=3;k>(-1);k--)
  106.       {
  107.          if(sound[k]) FreeMem(sound[k],(long)sizeof(struct IOAudio));
  108.          if(cbuf[k])  FreeMem(cbuf[k],BUFSIZE);
  109.       }
  110.       sound[0]=sound[1]=sound[2]=NULL;
  111.    }
  112.  
  113. /* Write any message to out. May be error or could be samples/second */
  114. /* You'll be sorry if you try to Write(Output()) to WorkBench!  8-)  */
  115.  
  116.    if(help) Write(Output(),string,(long)strlen(string));
  117.    else if(strlen(string))
  118.    {
  119.       strcpy(title,"Sound Error: ");   strcat(title,string);
  120.       setStatusWindo();  Delay(150L);
  121.    }
  122.  
  123. /* Clean up everything else */
  124.  
  125.    if(StatusWindo)      CloseWindow(StatusWindo);
  126.    if(IntuitionBase)    CloseLibrary(IntuitionBase);
  127.    if(sbuffer)          FreeMem(sbuffer,sactual);
  128.    if(infofile)         FreeDiskObject(infofile);
  129.    if(IconBase)         CloseLibrary(IconBase);
  130.    if(!sound[3]) exit(10);
  131.    StatusWindo=NULL;    IntuitionBase=NULL;
  132.    sbuffer=NULL;   infofile=NULL;   IconBase=NULL;
  133.    sactual=0L; sstart=0L; savelock=0L; sps=0L; cycles=1L;
  134.    lock=0L;  k=0; stereo=0; left=1; right=1;
  135. }
  136.  
  137.  
  138. /*  Don't Allocate if Low Mem - by Bryce Nesbitt  */
  139. /* Aberations by RLS. 4096 should be fudge enough */
  140.  
  141. char *SafeAllocMem(size,flags)
  142. long size, flags;
  143. {
  144.    register char *p;
  145.    
  146.    if(p=(char *)AllocMem(size,flags))
  147.       if(AvailMem(MEMF_CHIP)<4096L)
  148.          { FreeMem(p,size);  return(NULL); }
  149.    return(p);
  150. }
  151.  
  152. /**** Status Window. Uses <CTRL> 'c' to abort.  ****/
  153.  
  154. void setStatusWindo()
  155. {
  156.     struct NewWindow w;
  157.     
  158. /* Try to Open Intuition and if successful, make a 'status' window */
  159.  
  160.     if(StatusWindo) CloseWindow(StatusWindo); StatusWindo=NULL;
  161.     if(!IntuitionBase)
  162.     {
  163.        IntuitionBase = (struct IntuitionBase *)
  164.                        OpenLibrary("intuition.library",REVISION);
  165.     }
  166.     if(!IntuitionBase) quit("");
  167.  
  168.     w.LeftEdge    =   82L;
  169.     w.TopEdge     =    0L;
  170.  
  171. /* if title==USAGE, the large Width value will abort the window open */
  172. /* This is just fine, because we don't WANT it to open in this case. */
  173.  
  174.     w.Width       = (long)(strlen(title)*8+8);
  175.     w.Height      =   10L;
  176.     w.DetailPen   =  0x01;
  177.     w.BlockPen    =  0x03;
  178.     w.Title       = (UBYTE *)title;
  179.     w.Flags       = SMART_REFRESH|NOCAREREFRESH|ACTIVATE|WINDOWDRAG;
  180.     w.IDCMPFlags  = VANILLAKEY;   /* So we can get <CTRL> 'c' message */
  181.     w.Type        = WBENCHSCREEN;
  182.     w.FirstGadget = NULL;
  183.     w.CheckMark   = NULL;
  184.     w.Screen      = NULL;
  185.     w.BitMap      = NULL;
  186.     w.MinWidth    = 0;
  187.     w.MinHeight   = 0;
  188.     w.MaxWidth    = 0;
  189.     w.MaxHeight   = 0;
  190.     StatusWindo = OpenWindow(&w);
  191.  
  192. /* Abort ONLY if cycles = 0 (loop) AND the window failed to open. */
  193. /* This set of conditions would otherwise result in an Endless and */
  194. /* Escape-proof loop. If cycles != 0, sound will end, sometime... */
  195.  
  196.     if(!StatusWindo&&(cycles==0L)) quit("");
  197. }
  198.  
  199.  
  200. /******** Load SoundFile 'sPath' & set cycles-sps-stereo *******/
  201.  
  202. void loadSound(sPath)
  203. char    *sPath[80];
  204. {
  205.    struct Filehandle    *sFile=NULL;
  206.    struct FileInfoBlock *finfo=NULL;
  207.    struct FileLock      *lock=NULL;
  208.           long          i, j;
  209.           char          string[5];
  210.  
  211. /* Allocate 256 bytes as work memory */
  212.  
  213.    if(!(sbuffer=SafeAllocMem(256L,MEMF_CLEAR|MEMF_PUBLIC)))
  214.         quit("No Work Memory!");
  215.  
  216. /* Check for and parse IFF data in first 256 bytes of file */
  217.  
  218.    if(!(sFile=Open(sPath,MODE_OLDFILE)))
  219.    {
  220.       sactual=256L;      quit("Can't Find SoundFile!");
  221.    }
  222.    Read(sFile,sbuffer,256L);              /* load the 1st 256 bytes */
  223.    for(sstart=0L, sps=0L, i=0L; i<252L; i+=4L)
  224.    {
  225.       strncpy(string,sbuffer+i,4);   string[4]=NULL;
  226.       if(!(strcmp(string,"VHDR")))        /* get samples per second */
  227.       {
  228.          for(j=0;j<(long)((UBYTE)sbuffer[i+20]);j++) sps+=256L;
  229.          sps += ((UBYTE)sbuffer[i+21L]);
  230.       }
  231.       if(!(strcmp(string,"CHAN")))            /* Channel Assignment */
  232.       {
  233.          if((sbuffer[i+7]==6)||(sbuffer[i+11]==6)) stereo=1;
  234.       }
  235.       if(!(strcmp(string,"BODY")))        /* get size of sound data */
  236.       {
  237.          for(j=0;j<4;j++) sactual+=(((UBYTE)sbuffer[i+7L-j])<<(8*j));
  238.          sstart = i+8L; i=252L;
  239.       }
  240.    }
  241.  
  242. /* if not in IFF format, get filesize from FileInfoBlock */
  243.  
  244.    if(!sactual)
  245.    {
  246.  
  247. /* Allocate a file info block, get size from it, and de-allocate */
  248.  
  249.       if((!(finfo=(struct FileInfoBlock *)
  250.